<!doctype html>
<html lang="zh-CN"><head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script>
    <title>薛尧的博客</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="" />

    
    
    
    <link rel="stylesheet" href="../../../css/theme.min.css">

    
    
    
    
    <link rel="stylesheet" href="../../../css/custom.min.css">
    

    
</head>
<body>
        <div id="content" class="mx-auto"><header class="container mt-sm-5 mt-4 mb-4 mt-xs-1">
    <div class="row">
        
        <div class="col-sm-4 col-12 text-sm-right text-center pt-sm-4">
            <a href="../../../" class="text-decoration-none">
                <img id="home-image" class="rounded-circle"
                    
                        src="https://ueyao.github.io/image-hosting/blog/avatar.png"
                    
                />
            </a>
        </div>
        <div class="col-sm-8 col-12 text-sm-left text-center">
        
            <h2 class="m-0 mb-2 mt-4">
                <a href="../../../" class="text-decoration-none">
                    
                        薛尧
                    
                </a>
            </h2>
            <p class="text-muted mb-1">
                
                    Java Developer | Short Video Creator
                
            </p>
            <ul id="nav-links" class="list-inline mb-2">
                
                
                    <li class="list-inline-item">
                        <a class="badge badge-white " href="../../../about/" title="关于">关于</a>
                    </li>
                
                    <li class="list-inline-item">
                        <a class="badge badge-white " href="../../../post/" title="文章">文章</a>
                    </li>
                
                    <li class="list-inline-item">
                        <a class="badge badge-white " href="../../../categories/" title="分类">分类</a>
                    </li>
                
            </ul>
            <ul id="nav-social" class="list-inline">
                
                    <li class="list-inline-item mr-3">
                        <a href="http://github.com/flowstone" target="_blank">
                            <i class="fab fa-github fa-1x text-muted"></i>
                        </a>
                    </li>
                
                    <li class="list-inline-item mr-3">
                        <a href="mailto:xueyao.me#gmail.com" target="_blank">
                            <i class="fas fa-at fa-1x text-muted"></i>
                        </a>
                    </li>
                
            </ul>
        </div>
    </div>
    <hr />
</header>
<div class="container">
    <div class="pl-sm-2">
        <div class="mb-3">
            <h3 class="mb-0">Java多线程-线程中止</h3>
            
            <small class="text-muted">发布于 2019-08-26</small>
        </div>

        <article>
            <h2 id="不正确的线程中止-stop">不正确的线程中止-Stop</h2>
<p>Stop:中止线程，并且清除监控器锁的信息，但是可能导致
线程安全问题，JDK不建议用。
Destroy: JDK未实现该方法。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">/**
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * @author simon
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> */</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">StopThread</span> <span style="color:#66d9ef">extends</span> Thread {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> 0, j <span style="color:#f92672">=</span> 0;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Override</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">run</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">synchronized</span> (<span style="color:#66d9ef">this</span>) {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// 增加同步锁，确保线程安全</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">++</span>i;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">try</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#75715e">// 休眠10秒,模拟耗时操作</span>
</span></span><span style="display:flex;"><span>                Thread.<span style="color:#a6e22e">sleep</span>(10000);
</span></span><span style="display:flex;"><span>            } <span style="color:#66d9ef">catch</span> (InterruptedException e) {
</span></span><span style="display:flex;"><span>                e.<span style="color:#a6e22e">printStackTrace</span>();
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">++</span>j;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/** * 打印i和j */</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">print</span>() {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;i=&#34;</span> <span style="color:#f92672">+</span> i <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34; j=&#34;</span> <span style="color:#f92672">+</span> j);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">/**
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * @author simon
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * 示例3 - 线程stop强制性中止，破坏线程安全的示例
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> */</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Demo</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) <span style="color:#66d9ef">throws</span> InterruptedException {
</span></span><span style="display:flex;"><span>        StopThread thread <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> StopThread();
</span></span><span style="display:flex;"><span>        thread.<span style="color:#a6e22e">start</span>();
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// 休眠1秒，确保i变量自增成功</span>
</span></span><span style="display:flex;"><span>        Thread.<span style="color:#a6e22e">sleep</span>(1000);
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// 暂停线程</span>
</span></span><span style="display:flex;"><span>        thread.<span style="color:#a6e22e">stop</span>(); <span style="color:#75715e">// 错误的终止</span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//thread.interrupt(); // @正确终止</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">while</span> (thread.<span style="color:#a6e22e">isAlive</span>()) {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// 确保线程已经终止</span>
</span></span><span style="display:flex;"><span>        } <span style="color:#75715e">// 输出结果</span>
</span></span><span style="display:flex;"><span>        thread.<span style="color:#a6e22e">print</span>();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>理想状态：要么自增成功i=1, j=1，要么自增失败i=0, j=0
真正程序执行结果：i=1, j=0</p>
<p><img src="https://ueyao.github.io/image-hosting/blog/2019/thread-stop-01.png" alt=""></p>
<p>没有保证同步代码块里面数据的一致性，破坏了线程安全
stop方法直接停止线程</p>
<h2 id="正确的线程中止-interrupt">正确的线程中止-interrupt</h2>
<p>如果目标线程在调用Object class的wait()、wait(long)或wait(long, int)方法、join()、join(long, int)或sleep(long, int)方法时被阻塞，那么Interrupt会生效，该线程的中断状态将被清除，抛出InterruptedException异常。</p>
<p>如果目标线程是被I/O或者NIO中的Channel所阻塞，同样，I/O操作会被中断或者返回特殊异常值。达到终止线程的目的。</p>
<p>如果以上条件都不满足，则会设置此线程的中断状态。</p>
<p>对Demo中的示例，stop()改成interrupt()后，最终输出为&quot;i=1 j=1&quot;，数据一致。</p>
<p><img src="https://ueyao.github.io/image-hosting/blog/2019/thread-stop-02.png" alt=""></p>
<h2 id="正确的线程中止-标志位">正确的线程中止-标志位</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">/** 通过状态位来判断 */</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Demo4</span> <span style="color:#66d9ef">extends</span> Thread {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">volatile</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">boolean</span> flag <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) <span style="color:#66d9ef">throws</span> InterruptedException {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">new</span> Thread(() <span style="color:#f92672">-&gt;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">try</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">while</span> (flag) { <span style="color:#75715e">// 判断是否运行</span>
</span></span><span style="display:flex;"><span>          System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;程序运行中&#34;</span>);
</span></span><span style="display:flex;"><span>          Thread.<span style="color:#a6e22e">sleep</span>(1000L);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      } <span style="color:#66d9ef">catch</span> (InterruptedException e) {
</span></span><span style="display:flex;"><span>        e.<span style="color:#a6e22e">printStackTrace</span>();
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }).<span style="color:#a6e22e">start</span>();
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// 3秒之后，将状态标志改为False，代表不继续运行</span>
</span></span><span style="display:flex;"><span>    Thread.<span style="color:#a6e22e">sleep</span>(3000L);
</span></span><span style="display:flex;"><span>    flag <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>    System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;程序运行结束&#34;</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>在上方代码逻辑中，增加一个判断，用来控制线程执行的中止。</p>
<p><img src="https://ueyao.github.io/image-hosting/blog/2019/thread-stop-03.png" alt=""></p>

        </article>
    </div>

    <div id="disqus_thread"></div>
<script>
    window.disqus_config = function () {
    
    
    
    };
    (function() {
        if (["localhost", "127.0.0.1"].indexOf(window.location.hostname) != -1) {
            document.getElementById('disqus_thread').innerHTML = 'Disqus comments not available by default when the website is previewed locally.';
            return;
        }
        var d = document, s = d.createElement('script'); s.async = true;
        s.src = '//' + "xie-yao-de-bo-ke" + '.disqus.com/embed.js';
        s.setAttribute('data-timestamp', +new Date());
        (d.head || d.body).appendChild(s);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="https://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

            </div>
        </div><footer class="text-center pb-1">
    <small class="text-muted">
        
        &copy; Copyright 2024
        
        |
        <a href="https://beian.miit.gov.cn/" target="_blank">苏ICP备14012079号</a>
        <br />
        由 <a href="https://gohugo.io/" target="_blank">Hugo</a> 强力驱动
        | 主题 <a href="https://github.com/austingebauer/devise" target="_blank">Devise</a>
        <br />

    </small>
</footer></body>
</html>
